#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <adime.h>
#include "allegro.h"

using namespace std;

#define TRUE        -1
#define FALSE       0
#define MAP_W       640
#define MAP_H       400
#define CELL_W      16
#define CELL_H      16
#define PLAINS      'P'
#define MOUNTAINS   'M'
#define SEA         'S'
#define RIVER       'W'
#define RCROSS      'C'
#define ROAD        'R'

int prg_exit = FALSE;

volatile int gams = 0;
void game_timer_handler() {
    gams++;
}
END_OF_FUNCTION(game_timer_handler);

int WHITE=0;
string map(1000,'P');
BITMAP *img;
BITMAP *buf;
char selected_curs = PLAINS;
bool inverted = FALSE;
string fname;

void set_shutdown() {
    prg_exit = TRUE;
}

// convert int to string
string itos(int i) {
    stringstream s;
    s << i;
    return s.str();
}

void save_map(string fname) {
    ofstream fstream(fname.c_str());
    if(!fstream) {
        allegro_message("Error: Can't write to %s\n",fname.c_str());
        return;
    }
    fstream << map;
    fstream.close();
    alert("","Map saved","","&Ok",NULL,'o',0);
}

void load_map(string fname) {
    ifstream fstream(fname.c_str());
    if(!fstream) {
        return;
    }
    fstream >> map;
    fstream.close();
}

void draw_grid(BITMAP *buf) {
    for (int i = CELL_W; i < MAP_W; i+=CELL_W) {
        vline(buf,i,0,MAP_H,0);
    }
    for (int i = CELL_H; i < MAP_H; i+=CELL_H) {
        hline(buf,0,i,MAP_W,0);
    }
}

void put_mapmarks(BITMAP *buf) {
    int i = 0;
    int color = WHITE;
    if(inverted) color = makecol16(0,0,0);
    string mark = "S\0";
    mark[1] = '\0';
    for (int y = 0; y < MAP_H; y+=CELL_H) {
        for (int x = 0; x < MAP_W; x+=CELL_W) {
            mark[0] = map.at(i);
            textout_ex(buf, font, mark.c_str(), x, y, color, -1);
            i++;
        }
    }
}

void handle_mouse() {
    int xcells = MAP_W/CELL_W;
    int cell = (mouse_y/CELL_H)*xcells+mouse_x/CELL_W;
    map.at(cell) = selected_curs;
}

void handle_map(DIALOG *d) {
    static int my_count = 0;
    if (my_count < gams) {
        scare_mouse();
        blit(buf, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
        unscare_mouse();
        gams = 0;
    }
    if(my_count == gams) {
        if (mouse_b & 1 && mouse_y<401) handle_mouse();
        blit(img, buf, 0, 0, 0, 0, MAP_W, MAP_H);
        draw_grid(buf);
        put_mapmarks(buf);
    }
}

int select_curs(DIALOG *d, int button_index) {
    switch (button_index) {
        // Plains
        case 1: selected_curs = PLAINS; break;
        // Mountains
        case 2: selected_curs = MOUNTAINS; break;
        // Sea
        case 3:  selected_curs = SEA; break;
        // River
        case 4:  selected_curs = RIVER; break;
        // RiverCross
        case 5:  selected_curs = RCROSS; break;
        // Road
        case 6:  selected_curs = ROAD; break;

        default: ;
    }
    return 0;
}

int invert_markers(DIALOG *d) {
    inverted = !inverted;
    return 0;
}

int dlg_save(DIALOG *d) {
    save_map(fname+".map");
    return 0;
}

/* run:
   Opens the dialog.
*/
void run(void) {
   adime_callback = handle_map;

   /* This might make animation more smooth under windows. */
   adime_yield = FALSE;

   /* Open the dialog. */
   adime_lowlevel_dialogf("Menu:",
                        0, 401, 640,
                        "%buttonrow[ Plains , Mountains  , Sea ,"
                        " River, RiverCross , Road ]"
                        "%button[ inv  ]"
                        "%button[ Save ]",
                        select_curs,
                        invert_markers,
                        dlg_save);
}

int main(int argc, char *argv[]) {
    RGB *pal = NULL;

    allegro_init();
    if (argc<2) {
        allegro_message("Image file not specified!");
        return 1;
    }

    fname = argv[1];
    fname.resize(fname.find_last_of('.'));

    install_timer();
    install_keyboard();
    install_mouse();
    //set_window_close_hook(set_shutdown);
    LOCK_VARIABLE(gams);
    LOCK_FUNCTION(game_timer_handler);
    set_color_conversion(COLORCONV_NONE);
    set_color_depth(16);
    WHITE=makecol16(255,255,255);

    if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0) != 0) {
        set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
        allegro_message("Error setting graphics mode\n%s\n", allegro_error);
        return 1;
    };

    /* Install Adime. */
    if (adime_init() != 0) {
      set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
      allegro_message("Error initializing Adime.\n");
      exit(1);
    }
    adime_window_visible = FALSE;
    adime_window_title_spacing = 1;
    adime_window_button_spacing = 5;
    adime_window_between_button_spacing = 2;
    adime_window_line_spacing = 5;


    install_int_ex(game_timer_handler,BPS_TO_TIMER(30));
    img = load_bitmap(argv[1],pal);
    load_map(fname+".map");
    buf = create_bitmap(640,400);
    run();

    if (alert("","Save data to file?","","&Yes","&No",'y','n')==1) {
        save_map(fname+".map");
    }

    destroy_bitmap(buf);
    destroy_bitmap(img);

    allegro_exit();

    return 0;
}

END_OF_MAIN();
                